package util;

/**
 * @author peedarpk
 */

import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.Random;

import sim.VehicleRunnable;

public class Util {

	public static Point2D.Double getNextPoint(Point2D.Double startPoint, Point2D.Double endPoint, double distance) {
		Point2D.Double nextPoint = null;

		double theta = getAngle(startPoint.getX(), startPoint.getY(), endPoint.getX(), endPoint.getY());

		Double nextX = startPoint.getX() + (distance * Math.cos(theta));

		Double nextY = startPoint.getY() - (distance * Math.sin(theta));

		nextPoint = new Point2D.Double(nextX, nextY);

		return nextPoint;
	}

	public static Point getNextPoint2(Point startPoint, Point endPoint) {

		Point nextPoint = null;

		Point p1;
		Point p2;
		p1 = startPoint;
		p2 = endPoint;
		// p1 and p2 inits

		// you don't use abs value and use the still point as the first one of
		// the subtraction
		double deltaX = p2.getX() - p1.getX();
		double deltaY = p2.getY() - p1.getY();

		// now you know how much far they are
		double coeff = 0.1; // this coefficient can be tweaked to decice how
							// much near the two points will be after the
							// update.. 0.5 = 50% of the previous distance

		p1.setLocation(p1.getX() + coeff * deltaX, p1.getY() + coeff * deltaY);

		nextPoint = p1;
		return nextPoint;
	}

	private static double getAngle(double x1, double y1, double x2, double y2) {

		// slope of the line
		double slope = (y2 - y1) / (x2 - x1); // Get gradient of line.

		if (x2 == x1) {// Protect against divide by 0
			if (y2 == y1)
				return -1;
			else if (y2 < y1)
				return Math.PI / 2;
			else
				return 3 * (Math.PI / 2);
		}

		/**
		 * Slope is the opposite sign to what you would expect due to computer
		 * screen geometry differing from math X-Y geometry. Value to return
		 * depends on what quadrant the line is in.
		 */

		if (x2 >= x1 && y2 <= y1) {
			return (-Math.atan(slope)); // 1st quadrant.
		} else if (x2 < x1 && y2 <= y1) {
			return (Math.PI - Math.atan(slope)); // 2nd quadrant.
		} else if (x2 < x1 && y2 > y1) {
			return (Math.PI - Math.atan(slope)); // 3rd quadrant.
		} else {
			return (2 * Math.PI - Math.atan(slope)); // 4th quadrant.
		}
	}

	public static double getAngle(Point2D.Double start, Point2D.Double end) {
		return getAngle(start.getX(), start.getY(), end.getX(), end.getY());

	}

	public static double kmphToMetersPerSec(double kmph) {
		double mps = 0;
		mps = (kmph * 1000) / (60 * 60);
		return mps;
	}

	public static double mpsToDistance(double mps) {
		double distance = 0;

		distance = (mps * VehicleRunnable.DELAY) / 1000;

		return distance;

	}

	public static double distanceToPixels(double distance) {
		double pix = 0;
		pix = distance * 0.5;
		return pix;
	}

	public static int showRandomInteger(int aStart, int aEnd, Random aRandom) {
		if (aStart > aEnd) {
			throw new IllegalArgumentException("Start cannot exceed End.");
		}
		long range = (long) aEnd - (long) aStart + 1;
		long fraction = (long) (range * aRandom.nextDouble());
		int randomNumber = (int) (fraction + aStart);

		return randomNumber;
	}

}
